﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace Dycox.ComponentModel
{
    public class SimpleTypeDescriptorContext : ITypeDescriptorContext
    {
        IServiceProvider _svcProvider;
        ITypeDescriptorContext _innerContext;

        public SimpleTypeDescriptorContext(object instance, PropertyDescriptor property)
            : this(instance, property, null)
        {
        }

        public SimpleTypeDescriptorContext(ITypeDescriptorContext innerContext)
            : this(innerContext.Instance, innerContext.PropertyDescriptor, innerContext)
        {
        }

        public SimpleTypeDescriptorContext(object instance, PropertyDescriptor property, IServiceProvider serviceProvider)
        {
            if (instance == null)
                throw new ArgumentNullException("instance");
            if (property == null)
                throw new ArgumentNullException("property");

            _instance = instance;
            _property = property;

            _svcProvider = serviceProvider;
            _innerContext = serviceProvider as ITypeDescriptorContext;
            
        }

        public IContainer Container
        {
            get
            {
                if (_innerContext != null)
                    return _innerContext.Container;
                else
                    return null;
            }
        }

        object _instance;

        public object Instance
        {
            get { return _instance; }
        }

        public void OnComponentChanged()
        {
            if (_innerContext != null)
                _innerContext.OnComponentChanged();
        }

        public bool OnComponentChanging()
        {
            if (_innerContext != null)
                return _innerContext.OnComponentChanging();
            else
                return false;
        }

        private PropertyDescriptor _property;

        public PropertyDescriptor PropertyDescriptor
        {
            get { return _property; }
        }

        public object GetService(Type serviceType)
        {
            if (_svcProvider != null)
                return _svcProvider.GetService(serviceType);
            else
                return null;
        }

        public void SetValue(object value)
        {
            SetValue(value, true);
        }

        public void SetValue(object value, bool convert)
        {
            if (convert)
                value = Dycox.Utils.ConvertUtil.ConvertType(value, this);
            _property.SetValue(_instance, value);
        }

        public object GetValue()
        {
            return _property.GetValue(_instance);
        }

        public static SimpleTypeDescriptorContext Create(object instance, string propertyName)
        {
            if (instance == null)
                throw new ArgumentNullException("instance");
            if (propertyName == null)
                throw new ArgumentNullException("propertyName");

            PropertyDescriptorCollection coll = TypeDescriptor.GetProperties(instance);
            PropertyDescriptor p = coll[propertyName];

            if (p == null)
                throw new ArgumentException(SR.GetString("property_not_found", propertyName, instance.GetType().FullName));

            return new SimpleTypeDescriptorContext(instance, p);
        }
    }
}
